package com.zlc.common.util.context;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zlc.common.annotation.ResourceAnno;
import com.zlc.common.annotation.SyncResourceConstant;
import com.zlc.common.common.constant.ResourceCategoryEnum;
import com.zlc.common.common.constant.ResourceTypeEnum;
import com.zlc.common.common.service.ContextHolder;
import com.zlc.common.core.resource.model.vo.MayanPlatSystemResourceVo;
import com.zlc.common.core.resource.model.vo.MayanPlatSystemVo;
import com.zlc.common.core.resource.service.MayanPlatSystemResourceService;
import com.zlc.common.core.resource.service.MayanPlatSystemService;
import com.zlc.common.core.sys.model.vo.MayanPlatParameterVo;
import com.zlc.common.util.PlatUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SysResourceInit {


    private ApplicationContext context;

    @Autowired
    private MayanPlatSystemResourceService mayanPlatSystemResourceService;
    @Autowired
    private MayanPlatSystemService mayanPlatSystemService;

    public void initResource(ApplicationContext context) {
        this.context = context;

        Map<String, Object> resourceBeans = context.getBeansWithAnnotation(SyncResourceConstant.class);
        ContextHolder.setDefaultUser();
        List<MayanPlatSystemVo> systemVos = mayanPlatSystemService.queryVoList(new LambdaQueryWrapper<>());
        List<String> systemCodes = systemVos.stream().map(MayanPlatSystemVo::getSystemCode).collect(Collectors.toList());
        //查询所有系统参数
        List<MayanPlatSystemResourceVo> allResources = mayanPlatSystemResourceService.queryVoList(new LambdaQueryWrapper<>());
        Map<String, List<MayanPlatSystemResourceVo>> resourceMap = allResources.stream().collect(Collectors.groupingBy(MayanPlatSystemResourceVo::getSystemCode));

        //需要保存的参数
        List<MayanPlatParameterVo> saveList = new ArrayList<>();
        for (Object resourceBean : resourceBeans.values()) {
            SyncResourceConstant syncAnn = resourceBean.getClass().getAnnotation(SyncResourceConstant.class);
            String systemCode = syncAnn.systemCode();
            if (!systemCodes.contains(systemCode)) {
                log.error("同步系统资源, 系统标识:{} 不存在!", systemCode);
                continue;
            }
            List<MayanPlatSystemResourceVo> existResources = resourceMap.get(systemCode);
            Map<String, MayanPlatSystemResourceVo> existResourceMap = new HashMap<>();
            if (!ObjectUtils.isEmpty(existResources)) {
                existResourceMap = existResources.stream().collect(Collectors.toMap(MayanPlatSystemResourceVo::getResourceCode, e -> e));
            }

            List<MayanPlatSystemResourceVo> saveResources = new ArrayList<>();
            Field[] fields = resourceBean.getClass().getDeclaredFields();
            for (Field field : fields) {
                MayanPlatSystemResourceVo saveResourceVo = new MayanPlatSystemResourceVo();
                field.setAccessible(true);
                ResourceAnno annotation = field.getAnnotation(ResourceAnno.class);
                if (annotation == null) {
                    continue;
                }
                String resourceCode = annotation.resourceCode();
                String resourceName = annotation.resourceName();
                String icon = annotation.icon();
                String urlPath = annotation.urlPath();
                ResourceCategoryEnum category = annotation.category();
                ResourceTypeEnum type = annotation.type();
                String parentResourceCode = annotation.parentResourceCode();
                int sort = annotation.sort();

                MayanPlatSystemResourceVo existResourceVo = existResourceMap.get(resourceCode);
                if (existResourceVo != null) {
                    continue;
                }
                if (!ObjectUtils.isEmpty(parentResourceCode)) {
                    MayanPlatSystemResourceVo parentResource = existResourceMap.get(parentResourceCode);
                    if (ObjectUtils.isEmpty(parentResource)) {
                        parentResource = saveResources.stream().filter(e -> e.getResourceCode().equals(parentResourceCode)).findFirst().orElse(null);
                        if(ObjectUtils.isEmpty(parentResource)) {
                            log.error("同步系统资源, 父资源:{} 不存在!", parentResourceCode);
                            continue;
                        }
                    }
                    saveResourceVo.setParentResourceId(parentResource.getResourceId());
                    String resourceType = parentResource.getResourceType();
                    ResourceTypeEnum parentType = ResourceTypeEnum.getByCode(resourceType);
                    if (parentType != null && parentType.ordinal() > type.ordinal()) {
                        log.error("同步系统资源, 资源:{} 类型:{} 不能小于父资源:{} 类型:{}", resourceCode, type, parentResourceCode, parentType);
                        continue;
                    }
                }
                saveResourceVo.setSystemCode(systemCode);
                saveResourceVo.setResourceCategory(category.name());
                saveResourceVo.setResourceType(type.name());
                saveResourceVo.setResourceCode(resourceCode);
                saveResourceVo.setResourceName(resourceName);
                saveResourceVo.setUrlPath(urlPath);
                saveResourceVo.setIcon(icon);
                saveResourceVo.setResourceId(PlatUtils.uuid());
                saveResourceVo.setOrder(sort);
                saveResources.add(saveResourceVo);
            }
            if(!ObjectUtils.isEmpty(saveResources)) {
                mayanPlatSystemResourceService.saveVoList(saveResources);
            }
        }
    }
}
